//////////////////////////////////////////////////////////////////////////////////
//	 Copyright 2011 by Yosef Grabivker, ryuho@homenetworksoft.com
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//////////////////////////////////////////////////////////////////////////////////

#include <wx/wx.h>
#include <wx/dcbuffer.h>
#include <wx/clipbrd.h>
#include "statctrl.h"

#define TEXT_START	0
#define PERC_VAL_SZ	40

BEGIN_EVENT_TABLE(CStatCtrl, wxPanel)
	EVT_MOTION(CStatCtrl::OnMouseMove)
	EVT_LEAVE_WINDOW(CStatCtrl::OnMouseLeave)
	EVT_RIGHT_DOWN(CStatCtrl::OnMenu)
	EVT_MENU(wxID_COPY, CStatCtrl::OnCopy)
END_EVENT_TABLE()

CStatCtrl::CStatCtrl(wxWindow* pParent, const wxString& strLabel, STATMAP& stat):
	wxPanel(pParent, wxID_ANY,0,0,100,200), m_strLabel(strLabel), m_stat(stat)
{
	Connect(wxEVT_PAINT, wxPaintEventHandler(CStatCtrl::OnPaint));
	Connect(wxEVT_SIZE, wxSizeEventHandler(CStatCtrl::OnSize));
	
	SetBackgroundStyle(wxBG_STYLE_CUSTOM);
}

void CStatCtrl::CalculateTotal()
{
	m_nTotal = 0;

	for(STATMAP::iterator i = m_stat.begin();i!=m_stat.end();i++)
	{
		m_nTotal+=i->second;
	}
}

CStatCtrl::~CStatCtrl(void)
{
}

void CStatCtrl::Update()
{
	CalculateTotal();

	m_pairs.erase(m_pairs.begin(), m_pairs.end());

	for(STATMAP::iterator i = m_stat.begin();i!=m_stat.end();i++)
	{
		STATPAIR pair;

		pair.str = i->first;
		pair.val = i->second;

		m_pairs.push_back(pair);
	}

	m_pairs.sort();


	Refresh();
}

void CStatCtrl::OnSize(wxSizeEvent& event)
{
	Refresh();
}

void CStatCtrl::OnPaint(wxPaintEvent& event)
{
	wxSize szMe = GetClientSize();
	wxBufferedPaintDC dc(this);

	//Clear
	dc.SetBackground(*wxWHITE_BRUSH);
	dc.Clear();

	DrawBorder(dc);

	DrawTitle(dc);

	DrawStat(dc);
}

void CStatCtrl::OnMouseMove(wxMouseEvent& event)
{
	m_bValid = false;

	m_x = event.m_x;
	m_y = event.m_y;

	Refresh();

	//m_x = m_y = 0;
}

void CStatCtrl::OnMouseLeave(wxMouseEvent& event)
{
	m_bValid = false;

	m_x = 0;
	m_y = 0;

	Refresh();
}

void CStatCtrl::OnMenu(wxMouseEvent& event)
{
	Refresh();
	
	if ( m_bValid )
	{
		wxMenu* pMenu = new wxMenu();
		pMenu->Append(wxID_COPY,  _("Copy") );
	
		DoPopupMenu(pMenu, m_x, m_y );
	}

	Refresh();
}

void CStatCtrl::OnCopy(wxCommandEvent& event)
{
	//if ( m_bValid )
	{
		wxClipboard cp;

		if (cp.Open())
		{
			cp.SetData( new wxTextDataObject(m_cur.str) );

			cp.Flush();

			cp.Close();
		}
	}

	Refresh();
}

void CStatCtrl::DrawBorder(class wxMemoryDC& dc)
{
	wxColour 	grayLt(228,228,228);
	wxColour 	gray(127,127,127);
	wxPen		grltPen(grayLt);
	wxPen		grPen(gray);
	wxSize szMe = GetClientSize();

	dc.SetPen(grPen);

	dc.DrawLine(0, 0, szMe.x, 0 );
	dc.DrawLine(0, 0, 0, szMe.y );

	dc.SetPen(grltPen);

	dc.DrawLine(0, szMe.y-1, szMe.x, szMe.y-1 );
	dc.DrawLine(szMe.x-1, 0, szMe.x-1, szMe.y );
}

void CStatCtrl::DrawTitle(class wxMemoryDC& dc)
{
	wxSize szMe = GetClientSize();
	wxCoord w, h, xStart, yStart;
	wxFont  font(8, wxFONTFAMILY_DEFAULT,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL|wxFONTFLAG_ANTIALIASED);
	wxColor color(0, 0, 0);
	wxColour 	grayLt(228,228,228);
	wxColour 	gray(127,127,127);
	wxPen		grPen(gray);
	
	dc.SetTextForeground(color);
	dc.SetFont(font);
	
	dc.GetTextExtent(m_strLabel, &w, &h);
	
	xStart = (szMe.x-w)/2;
	yStart = TEXT_START;

	wxRect rc;
	rc.x=rc.y=1;
	rc.width  = szMe.x-1;
	rc.height = h+2;

	dc.GradientFillLinear( rc, gray, grayLt, wxALL);

	dc.SetPen(grPen);
	dc.DrawLine(1, rc.height, szMe.x-2, rc.height );

	m_yHeaderLast = rc.height;
	
	dc.SetTextForeground(color);
	dc.SetTextBackground(*wxWHITE);
	
	dc.DrawText(m_strLabel, xStart, yStart);
}

void CStatCtrl::DrawStat(class wxMemoryDC& dc)
{
	wxSize szMe = GetClientSize();
	wxFont  font(8, wxFONTFAMILY_DEFAULT,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL|wxFONTFLAG_ANTIALIASED);
	wxCoord w, h, xStart, yStart;
	wxColour 	gray(127,127,127);
	wxPen		grPen(gray);
	wxString    strPerc;
	wxBrush		br( wxColour(220,220,220) );
	wxBrush		brSel( wxColour(49,106,197) );
	//wxBrush		brSel( wxColour(224,236,255) );
	
	m_bValid = false;

	dc.SetFont(font);
	dc.SetPen(grPen);

	dc.GetTextExtent(wxT("test"), &w, &h);

	xStart=4, yStart=m_yHeaderLast;

	STATPAIRS::iterator iCur = m_pairs.begin();

	wxCoord percStart = szMe.x-PERC_VAL_SZ;

	int k=0;

	for(int i=yStart;;i+=h+2)
	{
		dc.DrawLine(1, i, szMe.x-2, i );

		if (i+h+2>szMe.y) break;

		if (0!=k++%2)
		{
			dc.SetBrush(br);
			dc.DrawRectangle(0,i,szMe.x+1,h+3);
		}

		if ( iCur!=m_pairs.end() )
		{
			if ( m_x && m_y )
			{
				wxRect rc(0,i,szMe.x+1,h+2);

				if ( rc.Contains(m_x, m_y) )
				{
					dc.SetBrush(brSel);
					dc.DrawRectangle(0,i,szMe.x+1,h+3);

					m_cur = *iCur;
					m_bValid = true;
				}
			}
			
			dc.DrawText(iCur->str, xStart, i);

			strPerc = wxString::Format(wxT(" %2.2u %%"),m_nTotal?(iCur->val*100)/m_nTotal:0);

			dc.DrawText( strPerc, percStart+2, i);

			iCur++;
		}
	}

	dc.DrawLine(percStart, yStart, percStart, szMe.y-2 );


	/*
	while(szMe.y>yStart+2*8)
	{
		dc.DrawLine(1, yStart, szMe.x-2, yStart );
		yStart+=h+2;

		if ( i!=m_stat.end() )
		{
			dc.DrawText(i->first, xStart, yStart-2*8);

			strPerc = wxString::Format(wxT(" %2.u %%"),m_nTotal?(i->second*100)/m_nTotal:0);

			dc.DrawText( strPerc, percStart+2, yStart-2*8);

			i++;
		}
	}*/




	/*
	for(STATMAP::iterator i = m_stat.begin();i!=m_stat.end();i++)
	{
		dc.DrawText(i->first, xStart, yStart);
		yStart+=h+2;
		
		dc.DrawLine(1, yStart, szMe.x-2, yStart );
	}*/
}